package logger

import (
	"go-quick/interface/ilogger"
	"go-quick/logger/formatter"
	"io"
	"os"
	"sync"
)

const (
	JsonFormat   LoggerFormat = iota // Json
	TextFormat                       //  文本
	CustomFormat                     // 自定义
)

type (

	// LoggerFormat 日志格式
	LoggerFormat int

	// QuickLogger 日志实现
	QuickLogger struct {
		Prefix       string
		Level        ilogger.LogLevel
		Formatter    ilogger.IFormatter
		TimeFormat   string
		Lock         ilogger.ILock
		Out          io.Writer
		Hooks        ilogger.IHook       // 钩子函数
		ReportCaller bool                // 是否输出调用信息
		entryPool    sync.Pool           // 对象池
		BufPool      ilogger.IBufferPool // 缓冲池
	}
)

func Default() *QuickLogger {
	logger := &QuickLogger{
		Out:        os.Stderr,
		Prefix:     "Quick",
		TimeFormat: ilogger.DefaultTimeFormat,
		Level:      ilogger.DefaultLevel,
		Lock:       NewLock(),
		Hooks:      DefaultHooks(),
		Formatter:  formatter.DefaultTextFormatter(),
	}
	return logger
}

// isLevelEnabled 检查日志记录器的日志级别是否大于设置的level参数
func (q *QuickLogger) isLevelEnabled(level ilogger.LogLevel) bool {
	return q.Level >= level
}

func (q *QuickLogger) getEntry() ilogger.IEntry {
	entry, ok := q.entryPool.Get().(ilogger.IEntry)
	if ok {
		return entry
	} else {
		entry = NewEntry(q)
		q.entryPool.Put(entry)
	}
	return entry
}

func (q *QuickLogger) releaseEntry(entry ilogger.IEntry) {
	entry.Clear()
	q.entryPool.Put(entry)
}

// logf 带格式化的日志
func (q *QuickLogger) logf(level ilogger.LogLevel, format string, args ...any) {
	if q.isLevelEnabled(level) {
		entry := q.getEntry()
		entry.LogF(level, format, args...)
		q.releaseEntry(entry)
	}
}

// logf 带格式化的日志
func (q *QuickLogger) log(level ilogger.LogLevel, args ...any) {
	if q.isLevelEnabled(level) {
		entry := q.getEntry()
		entry.Log(level, args...)
		q.releaseEntry(entry)
	}
}

func (q *QuickLogger) WithFields(fields ilogger.Fields) ilogger.ILogger {
	return q
}

func (q *QuickLogger) WithField(key string, value any) ilogger.ILogger {
	entry := q.getEntry()
	entry.WithField(key, value)
	return q
}

func (q *QuickLogger) InfoF(format string, args ...any) {
	q.logf(ilogger.InfoLevel, format, args...)
}

func (q *QuickLogger) Info(args ...any) {
	q.log(ilogger.InfoLevel, args...)
}

func (q *QuickLogger) DebugF(format string, args ...any) {
	q.logf(ilogger.DebugLevel, format, args...)
}

func (q *QuickLogger) Debug(args ...any) {
	q.log(ilogger.DebugLevel, args...)
}

func (q *QuickLogger) WarnF(format string, args ...any) {
	q.logf(ilogger.WarnLevel, format, args...)
}

func (q *QuickLogger) Warn(args ...any) {
	q.log(ilogger.WarnLevel, args...)
}

func (q *QuickLogger) ErrorF(format string, args ...any) {
	q.logf(ilogger.ErrorLevel, format, args...)
}

func (q *QuickLogger) Error(args ...any) {
	q.log(ilogger.ErrorLevel, args...)
}

func (q *QuickLogger) FailF(format string, args ...any) {
	q.logf(ilogger.FailLevel, format, args...)
}

func (q *QuickLogger) Fail(args ...any) {
	q.log(ilogger.FailLevel, args...)
}

func (q *QuickLogger) GetFormatter() ilogger.IFormatter {
	return q.Formatter
}

func (q *QuickLogger) GetOutput() io.Writer {
	return q.Out
}

func (q *QuickLogger) GetLock() ilogger.ILock {
	return q.Lock
}

func (q *QuickLogger) GetPrefix() string {
	return q.Prefix
}

func (q *QuickLogger) GetBufPool() ilogger.IBufferPool {
	if q.BufPool == nil {
		q.BufPool = DefaultBufPool()
	}
	return q.BufPool
}

func (q *QuickLogger) IsCaller() bool {
	return q.ReportCaller
}

func (q *QuickLogger) GetHooks() ilogger.IHook {
	return q.Hooks
}
